package org.jeecg.modules.system.service.impl;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.entity.SysDepart;
import org.keycloak.admin.client.CreatedResponseUtil;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Service
public class KeyCloakServiceImpl {
    @Value("${keycloak.resource}")
    private String keycloakClient;

    @Value("${keycloak.auth-server-url}")
    private String keycloakUrl;

    @Value("${keycloak.realm}")
    private String keycloakRealm;

    @Value("${keycloak.admin.user:admin}")
    private String keycloakAdminUser;

    @Value("${keycloak.admin.password:123456}")
    private String keycloakAdminPassword;

    Keycloak getKeycloakInstance() {
        return Keycloak.getInstance(
                keycloakUrl,
                "master",
                keycloakAdminUser,
                keycloakAdminPassword,
                "admin-cli");
    }

    public String addOrg(SysDepart sysDepart) {
        String groupId = "";
        Keycloak keycloak = getKeycloakInstance();
        if (StringUtils.isNotBlank(sysDepart.getParentId())) {
            GroupRepresentation subgroup = new GroupRepresentation();
            subgroup.setName(sysDepart.getDepartName());
            subgroup.setAttributes(new HashMap<String, List<String>>() {{
                put("code", new ArrayList<String>() {{
                    add(sysDepart.getOrgCode2());
                }});

                // 机构类型
                put("type", new ArrayList<String>() {{
                    if(sysDepart.getOrgCategory().equals("1"))
                        add("company");
                    if(sysDepart.getOrgCategory().equals("2"))
                        add("dept");
                }});
            }});
            Response response = keycloak.realm(keycloakRealm).groups().group(sysDepart.getParentId()).subGroup(subgroup);
//            if(response.getStatus() != 200)
//                return null;

            groupId = CreatedResponseUtil.getCreatedId(response);

        } else {
            GroupRepresentation group = new GroupRepresentation();
            group.setName(sysDepart.getDepartName());
            group.setAttributes(new HashMap<String, List<String>>() {{
                put("code", new ArrayList<String>() {{
                    add(sysDepart.getOrgCode2());
                }});

                // 机构类型
                put("type", new ArrayList<String>() {{
                    if(sysDepart.getOrgCategory().equals("1"))
                        add("company");
                    if(sysDepart.getOrgCategory().equals("2"))
                        add("dept");
                }});
            }});
            Response response = keycloak.realm(keycloakRealm).groups().add(group);
            groupId = CreatedResponseUtil.getCreatedId(response);
        }

        keycloak.close();

        return groupId;
    }

    public void updateOrg(SysDepart sysDepart) {
        Keycloak keycloak = getKeycloakInstance();
        GroupRepresentation group = new GroupRepresentation();
        group.setId(sysDepart.getId());
        group.setName(sysDepart.getDepartName());
        group.setAttributes(new HashMap<String, List<String>>() {{
            put("code", new ArrayList<String>() {{
                add(sysDepart.getOrgCode());
            }});

            // 机构类型
            put("type", new ArrayList<String>() {{
                if(sysDepart.getOrgCategory().equals("1"))
                    add("company");
                if(sysDepart.getOrgCategory().equals("2"))
                    add("dept");
            }});
        }});

        try {
            keycloak.realm(keycloakRealm).groups().group(sysDepart.getId()).update(group);

        } catch (Exception error) {
            throw new RuntimeException(error.getMessage());
        }
    }


    public void delOrg(String groupId) {
        Keycloak keycloak = getKeycloakInstance();
        try {
            keycloak.realm(keycloakRealm).groups().group(groupId).remove();

        } catch (Exception error) {
            throw new RuntimeException(error.getMessage());
        }
    }

    public List<GroupRepresentation> getOrgList() {
        Keycloak keycloak = getKeycloakInstance();
        return keycloak.realm(keycloakRealm).groups().groups();
    }

    public List<UserRepresentation> getUserList() {
        Keycloak keycloak = getKeycloakInstance();
        return keycloak.realm(keycloakRealm).users().list();
    }

    public String addUser(String username, String realname, String password, String orgCode) {
        Keycloak keycloak = getKeycloakInstance();
        UserRepresentation userRepresentation = new UserRepresentation();
        userRepresentation.setUsername(username);
        userRepresentation.setFirstName(realname);
        userRepresentation.setEnabled(true);

        CredentialRepresentation credentialRepresentation = new CredentialRepresentation();
        credentialRepresentation.setType(CredentialRepresentation.PASSWORD);
        credentialRepresentation.setValue(password);
        credentialRepresentation.setTemporary(false);
        userRepresentation.setCredentials(Arrays.asList(credentialRepresentation));
        Response response = keycloak.realm(keycloakRealm).users().create(userRepresentation);
        String userId = CreatedResponseUtil.getCreatedId(response);

        UserResource userResource = keycloak.realm(keycloakRealm).users().get(userId);
        if(StringUtils.isNotBlank(orgCode)) {
            userResource.joinGroup(orgCode);
            userResource.update(userRepresentation);
        }
        return userId;
    }

    public Result getUser(String userid) {
        Keycloak keycloak = getKeycloakInstance();
        UserResource userResource = keycloak.realm(keycloakRealm).users().get(userid);
        List<GroupRepresentation> groupRepresentationList = userResource.groups();

        UserRepresentation userRepresentation = userResource.toRepresentation();
        return Result.OK(userRepresentation);
    }

    public String getUserIdByName(String userName) {
        AtomicReference<String> userId = new AtomicReference<>();

        Keycloak keycloak = getKeycloakInstance();
        List<UserRepresentation> list = keycloak.realm(keycloakRealm).users().search(userName);
        list.forEach(item -> {
            if(item.getUsername().equals(userName))
                userId.set(item.getId());
        });

        return userId.get();
    }

    public void updateUser(String userid, String realname, String password, String groupId) {
        Keycloak keycloak = getKeycloakInstance();
        UserRepresentation userRepresentation = keycloak.realm(keycloakRealm).users().get(userid).toRepresentation();

        if(StringUtils.isNotBlank(realname)) {
            userRepresentation.setFirstName(realname);
        }
        userRepresentation.setEnabled(true);

        try {
            UserResource userResource = keycloak.realm(keycloakRealm).users().get(userid);

            if(StringUtils.isNotBlank(password)){
                CredentialRepresentation credentialRepresentation = new CredentialRepresentation();
                credentialRepresentation.setType(CredentialRepresentation.PASSWORD);
                credentialRepresentation.setValue(password);
                credentialRepresentation.setTemporary(false);
                userRepresentation.setCredentials(Arrays.asList(credentialRepresentation));
            }
            userResource.update(userRepresentation);

            List<GroupRepresentation> oldGroups = keycloak.realm(keycloakRealm).users().get(userid).groups();
            if (CollectionUtils.isNotEmpty(oldGroups)) {
                oldGroups.forEach(oldGroup -> {
                    userResource.leaveGroup(oldGroup.getId());
                });
            }

            // 異常 java.lang.RuntimeException: HTTP 404 Not Found
            if(groupId != null) {
                userResource.joinGroup(groupId);
            }

        } catch (Exception error) {
            throw new RuntimeException(error.getMessage());
        }

//        if (CollectionUtils.isNotEmpty(groups)) {
//            groups.forEach(gid -> {
//                userResource.joinGroup(gid);
//            });
//        }

    }

    @GetMapping("/deluser")
    public void deleteUser(String userid) {
        Keycloak keycloak = getKeycloakInstance();

        try {
            keycloak.realm(keycloakRealm).users().delete(userid);

        }catch (Exception error) {
            throw new RuntimeException(error.getMessage());
        }
    }
}

